from __future__ import division, print_function, unicode_literals

from board_controller import BoardController
from block_controller import BlockController
from config import GameConfig
from keyboard import Keyboard
from tile_model import TileModel
from timer import Timer


class GameController:
    __instance = None

    @staticmethod
    def getInstance():
        if GameController.__instance == None:
            GameController.__instance = GameController()
        return GameController.__instance

    def __init__(self):
        self._main_scene = None
        self._keyboard = None
        self._timer = None
        self._block_down_cooldown = 0
        self._keyboard_cooldown = 0
        self._board_controller = BoardController.getInstance()
        self._block_controller = BlockController.getInstance()

    def init(self, main_scene):
        self._main_scene = main_scene

        self._block_controller.init()

        # Create the board
        self._board_controller.init(self._main_scene)

        # Create the keyboard
        self._keyboard = Keyboard(self.operate_block)
        main_scene.add(self._keyboard)

        # Create the timer
        self._timer = Timer()
        main_scene.add(self._timer)
        self._timer.schedule(self.step)
        self._timer.pause()

    def operate_block(self, action):
        new_block = self._block_controller.create_next_block(action)
        tile_model = new_block.get_tile_model()
        self._keyboard_cooldown = GameConfig.KEYBOARD_LISTENER_INTERVAL

        if action == 'DOWN':
            self._block_down_cooldown = GameConfig.BLOCK_DOWN_TIME
            if not self._board_controller.check_collision(tile_model):
                self._board_controller.merge_tile(
                    self._block_controller.block.get_tile_model())
                self.render_board()
                self._keyboard.clear_keys()
                self.create_new_block()
                return
        if self._board_controller.check_valid(tile_model):
            self._block_controller.block = new_block
            self.render_board()

    def render_board(self):
        self._board_controller.render(
            self._block_controller.get_tile_model() +
            self._board_controller.get_tile_model()
        )

    def create_new_block(self):
        block = self._block_controller.create_block()
        block.set_pos(
            GameConfig.BOARD_TILE_WIDTH // 2 + 1,
            GameConfig.BOARD_TILE_HEIGHT
        )

    def start(self):
        self.create_new_block()
        self._timer.resume()

    def pause(self):
        print("Game Pause")

    def success(self):
        print("Game Success")

    def failure(self):
        print("Game Failure")

    def step(self, dt):
        self._block_down_cooldown -= dt
        if self._block_down_cooldown <= 0:
            self.operate_block('DOWN')
            self._block_down_cooldown = GameConfig.BLOCK_DOWN_TIME

        self._keyboard_cooldown -= dt
        if self._keyboard_cooldown <= 0:
            for action in self._keyboard.get_keys():
                if action in ['LEFT', 'RIGHT', 'DOWN']:
                    self.operate_block(action)
            self._keyboard_cooldown = GameConfig.KEYBOARD_LISTENER_INTERVAL
